package cn.miju.alipay.handler;

import cn.hutool.core.bean.BeanUtil;
import cn.miju.alipay.request.AlipayRefundOrderReq;
import cn.miju.alipay.response.AlipayBaseResp;
import cn.miju.alipay.response.AlipayRefundOrderResp;
import cn.miju.common.content.CodeMessage;
import cn.miju.common.exception.ValidateException;
import cn.miju.common.util.ValidationUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alipay.api.AlipayApiException;
import com.alipay.api.AlipayClient;
import com.alipay.api.AlipayResponse;
import com.alipay.api.request.AlipayTradeRefundRequest;
import com.alipay.api.response.AlipayTradeRefundResponse;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.math.RoundingMode;
import java.util.Set;

/**
 * <pre>
 * 订单退款
 * </pre>
 *
 * @author zhuming
 * @version 1.0.0
 * @since 2023-03-03 16:29
 */
@Slf4j
@Component
public class AlipayRefundOrderHandler extends AbstractAlipayHandler<AlipayRefundOrderReq, AlipayRefundOrderResp> {
    /**
     * 可选返回参数(如果接口所需参数不满足需求，可按照官方接口文档，原样传入对应参数)
     */
    private Set<String> optionalRespParams;
    /**
     * 请求参数前置处理
     *
     * @param req 请求参数
     * @return 结果
     */
    @Override
    public AlipayTradeRefundRequest beforeRequest(AlipayRefundOrderReq req) {
        ValidationUtil.validate(req);
        if (StringUtils.isBlank(req.getOutTradeNo()) && StringUtils.isBlank(req.getTradeNo())) {
            throw new ValidateException("传入商户订单号和支付宝交易号不能同时为空");
        }
        AlipayTradeRefundRequest request = new AlipayTradeRefundRequest();
        JSONObject bizContent = new JSONObject();
        bizContent.put("out_trade_no", req.getOutTradeNo());
        bizContent.put("out_request_no", req.getOutRefundNo());
        bizContent.put("trade_no", req.getTradeNo());
        bizContent.put("refund_amount", req.getRefundAmount().setScale(2, RoundingMode.HALF_DOWN));
        optionalRespParams = req.getOptionalRespParams();
        super.setOptionalReqParams(bizContent, req.getOptionalReqParams());
        request.setBizContent(bizContent.toString());
        return request;
    }

    /**
     * 核心执行
     *
     * @param req {@link AlipayRefundOrderReq}
     * @return {@link AlipayRefundOrderResp}
     */
    @Override
    public AlipayRefundOrderResp doPlan(AlipayRefundOrderReq req) {
        AlipayTradeRefundRequest request = this.beforeRequest(req);
        AlipayClient alipayClient = super.createAlipayClient(req.getAlipayProperties());
        log.info("API--alipay.trade.refund(统一收单交易退款接口)-->Request：{}", JSON.toJSONString(request));
        AlipayTradeRefundResponse response = null;
        try {
            response = alipayClient.execute(request);
        } catch (AlipayApiException e) {
            AlipayBaseResp baseResp = AlipayBaseResp.builder(CodeMessage.FAIL);
            log.error("[NO:{}]-API--alipay.trade.refund(统一收单交易退款接口)-->Exception：{}", e.getMessage(), e);
            return BeanUtil.copyProperties(baseResp, AlipayRefundOrderResp.class);
        }
        log.info("API--alipay.trade.refund(统一收单交易退款接口)-->Response：{}", JSON.toJSONString(response));
        return this.afterResponse(response);
    }

    /**
     * 响应参数后置处理
     *
     * @param resp 响应参数
     * @return 结果
     */
    @SneakyThrows
    @Override
    public AlipayRefundOrderResp afterResponse(AlipayResponse resp) {
        AlipayBaseResp baseResp = AlipayBaseResp.builder(CodeMessage.FAIL);
        AlipayTradeRefundResponse response = (AlipayTradeRefundResponse) resp;
        baseResp.setMsg(StringUtils.isEmpty(response.getSubMsg()) ? baseResp.getMsg() : response.getSubMsg());
        if (response.isSuccess()) {
            baseResp = AlipayBaseResp.builder(CodeMessage.SUCCESS);
            baseResp.setOptionalRespParams(super.getOptionalRespParams(response, optionalRespParams));
        }
        AlipayRefundOrderResp alipayRefundOrderResp = new AlipayRefundOrderResp();
        BeanUtil.copyProperties(baseResp, alipayRefundOrderResp);
        alipayRefundOrderResp.setTradeNo(response.getTradeNo());
        return alipayRefundOrderResp;
    }
}
